﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.WebSockets;
using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace XTYAPI.通讯.WebSokcet
{
    public class WebSocketServer
    {
        public event Action<string> ServerEvent;
        private HttpListener _httpListener;
        private CancellationTokenSource _cancellationTokenSource;
        List<WebSocket> webSockets = new List<WebSocket>();
        /// <summary>
        /// 初始化http监听口http://localhost:8080/
        /// </summary>
        /// <param name="url"></param>
        public WebSocketServer(string url= "http://localhost:8080/")
        {
            _httpListener = new HttpListener();
            _httpListener.Prefixes.Add(url);
            _cancellationTokenSource = new CancellationTokenSource();
        }
        /// <summary>
        /// 开始监听
        /// </summary>
        /// <returns></returns>
        public async Task Start()
        {
            _httpListener.Start();

            ServerEvent.Invoke("服务器开始启动监听");

            while (!_cancellationTokenSource.Token.IsCancellationRequested)
            {
                HttpListenerContext context = await _httpListener.GetContextAsync();
                if (context.Request.IsWebSocketRequest)
                {
                    ProcessWebSocketRequest(context);
                }
                else
                {
                    context.Response.StatusCode = 400;
                    context.Response.Close();
                }
            }
            _httpListener.Stop();
        }
        /// <summary>
        /// 停止监听
        /// </summary>
        public void Stop()
        {
            _cancellationTokenSource.Cancel();
        }
        /// <summary>
        /// 相应WebSocket客户端连接请求
        /// </summary>
        /// <param name="context"></param>
        private async void ProcessWebSocketRequest(HttpListenerContext context)
        {
            WebSocketContext webSocketContext = null;

            try
            {
                // 接受WebSocket连接请求
                webSocketContext = await context.AcceptWebSocketAsync(subProtocol: null);
                string url = context.Request.RemoteEndPoint.ToString();
                //Console.WriteLine("WebSocket client connected.");
                ServerEvent.Invoke($"WebSokcet客户端已连接{url}");
            }
            catch (Exception ex)
            {
                context.Response.StatusCode = 500;
                context.Response.Close();
                //Console.WriteLine($"WebSocket client connection error: {ex.Message}");
                ServerEvent.Invoke($"WebSocket客户端连接错误: {ex.Message}");
                return;
            }

            WebSocket webSocket = webSocketContext.WebSocket;
            webSockets.Add(webSocket);
            byte[] receiveBuffer = new byte[1024];

            while (webSocket.State == WebSocketState.Open)
            {
                // 接收客户端发送的消息
                WebSocketReceiveResult receiveResult;
                try
                {
                    receiveResult = await webSocket.ReceiveAsync(new ArraySegment<byte>(receiveBuffer), CancellationToken.None);

                    if (receiveResult.MessageType == WebSocketMessageType.Close)
                    {
                        // 如果收到关闭消息，则关闭WebSocket连接
                        await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "", CancellationToken.None);
                        ServerEvent.Invoke($"WebSokcet客户端已断开");
                        webSockets.Remove(webSocket);
                        //Console.WriteLine("WebSocket client disconnected.");
                    }
                    else
                    {
                        // 解析接收到的消息
                        string receivedMessage = Encoding.UTF8.GetString(receiveBuffer, 0, receiveResult.Count);
                        //Console.WriteLine($"Received message: {receivedMessage}");
                        ServerEvent.Invoke($"WebSokcet客户端接收的消息是{receivedMessage}");

                        // 将接收到的消息回显给客户端
                        byte[] sendBuffer = Encoding.UTF8.GetBytes(receivedMessage);
                        await webSocket.SendAsync(new ArraySegment<byte>(sendBuffer, 0, sendBuffer.Length), WebSocketMessageType.Text, true, CancellationToken.None);
                    }
                }
                catch (Exception ex)
                {
                    ServerEvent.Invoke($"WebSokcet客户端错误{ex.ToString()}");
                    ServerEvent.Invoke($"WebSokcet客户端下线{context.Request.RemoteEndPoint}");
                    webSockets.Remove(webSocket);
                }

            }
        }
        /// <summary>
        /// 向客户端群发消息
        /// </summary>
        /// <param name="str"></param>
        public async void SendClient(string str)
        {
            if (webSockets.Count == 0)
            {
                ServerEvent?.Invoke("webSocekt还没有客户端连上，发送不了：" + str);
                return;
            }
            if (!string.IsNullOrEmpty(str))
            {
                ServerEvent?.Invoke("向webSocekt客户端发送：" + str);
                var response = Encoding.UTF8.GetBytes(str);
                foreach (var item in webSockets)
                {
                    ServerEvent?.Invoke(str);
                    await item.SendAsync(new ArraySegment<byte>(response), WebSocketMessageType.Text, true, CancellationToken.None);
                }

            }
        }
    }
}
